We already know that C implements arrays by means of pointers. This means that I can de-reference a pointer by putting a subscript after it:
ptr[0] = 99 ;
This would set the memory location which ptr points at to the value 99. This is called de-referencing the pointer. Note that this means I can treat the memory which ptr points at as an array, whether this is sensible or not. Another way to de-reference a pointer is to use:
*ptr = 99 ;
Either of these statements would have the effect shown on the right.
This is another example of the way in which a given operator can be used to mean different things in different contexts. In this case the * before the variable says "follow the pointer to the thing it points at". This is potentially very confusing:
result = 5 * *ptr ;
In this expression we have * used twice. It is used as an operator between the thing that ptr points at and the value 5. It is also used to ask C to follow ptr to the thing that it points at. This is completely legal C, which will work out 5 times the value which ptr is pointing at and then set the variable result to this.
Try not to get * and & mixed up. & means "give me the address of" and * means "follow and find the thing that this points at". If you want a trick to remember this by, keep in mind that the Three Wise Men did not follow an ampersand!
The compiler will usually get upset if it thinks you are using a pointer or an address in the wrong way and it will produce compiler warnings. However, it will generally not stop you from running a program, even if it is unhappy with the code.
You should treat any warning involving pointers as an error, and ensure that you check your code carefully.
*ptr equals the contents of i, i.e. (99)